<script lang="ts" setup name="ManagePage">
import { nextTick, onMounted, reactive, ref } from 'vue'
import { ikTree } from 'iking-utils'
import useRouteStore from '@g/store/modules/route'
import { useFields } from './fields'
import { saveFile } from './download-file'
import { filterForm } from './widget-utils'
import { pageManage as api, modelManage } from '@/MainApp/apis/manage-design'
import menuApi from '@/MainApp/apis/menu'

const { t } = useConfig()
const { msgSuccess, msgError } = useMessage()
const routeStore = useRouteStore()

const tblData = ref<Array<any>>([])
const searchData = ref<any>({
  page: 1,
  rows: 15
})
const fields = ref([])
const countTotal = ref(0)
const loading = ref<boolean>(false)
const baseUrl = ref(import.meta.env.VITE_APP_API_BASEURL)
const token = useToken()

useFields().then((res: any) => {
  fields.value = res
})

const search = async () => {
  const params = {
    ...searchData.value
  }

  const ret = await api.select(params)
  countTotal.value = ret.total
  tblData.value = ret.data
}

const handleAdd = () => {
  modelMethods.open()
}

const handleEdit = (record: any) => {
  editMethods.open('update', record)
}

const handleDelete = async (record: any) => {
  const id = record.id
  const ret = await api.del(id)
  msgSuccess(ret.msg)
  search()
  routeStore.generateRoutesAtBack()
}

/** 模型选择对话框 begin */
const modelFormRef = ref<any>(null)
const modelState = reactive<any>({
  visible: false,
  modelList: []
})
const modelMethods = {
  open: () => {
    copyValue(formModel, new FormModel())
    modelState.visible = true
  },
  close: () => {
    modelState.visible = false
  },
  setModels: () => {
    let models = modelState.modelList.filter((item: any) => formModel.modelIds.includes(item.id))
    // 获取子模型
    let descendant: any = []
    for (const model of models) {
      const des = ikTree.descendant(model, { childrenField: 'slaveModels' }) ?? []
      descendant = descendant.concat(des)
    }
    // 合并
    let modelIds = descendant.map((item: any) => item.modelId).concat(models.map((item: any) => item.id))
    // 去重
    modelIds = [...new Set(modelIds)]
    models = modelState.modelList.filter((item: any) => modelIds.includes(item.id))
    editState.designerConfig.models = models
    console.log('editState.designerConfig.models ', editState.designerConfig.models)
  },
  next: async () => {
    try {
      modelFormRef.value?.validate()
    }
    catch (error) {
      return
    }
    modelMethods.close()
    await editMethods.loadTemplate()
    editMethods.open('add')
  },
  initModelList: async () => {
    const ret = await modelManage.selectAll(true)
    if (!ret.success) {
      msgError(ret.msg)
      return
    }
    modelState.modelList = ret.data
  }
}
onMounted(() => {
  modelMethods.initModelList()
})
/** 模型选择对话框 end */

/** 新增、编辑对话框 begin */
// 设计器引用
const designerRef = ref<any>(null)

class FormModel {
  id: string | null = null
  // 英文标识
  name = ''
  // 菜单名称
  title = ''
  description = ''
  json: any = null
  modelIds: string[] = []
  // 关联审批
  relateToApprove = false
  // 审批发起表单
  initiateFormId = ''
  // 审批节点表单列表
  approveNodeForms = []
}

const formModel = reactive(new FormModel())

const editState = reactive({
  title: '',
  operation: '',
  visible: false,
  json: '',
  // 全局表单配置
  globalFormConfig: {
    datasourceResponseConvert: '  const res = result.data;\n  const resultData = {\n    ...res,\n    status: res.success === true ? \'success\' : \'error\',\n    message: res.msg,\n    data: res.data\n  }\n  \n  if(resultData.status === \'error\'){\n     throw Error(resultData.message);\n  }\n  \n  result.data = resultData;\n  \n  return result;',
    dataSourceHost: import.meta.env.VITE_APP_API_BASEURL,
    uploadUrl: import.meta.env.VITE_APP_UPLOAD_URL,
    downloadUrl: import.meta.env.VITE_APP_DOWNLOAD_URL
  },
  designerConfig: {
    formTemplates: true,
    logoHeader: false,
    // 模型
    models: []
  } as any,
  globalDatasourceHeaders: [
    {
      name: 'Authorization',
      value: token
    }
  ],
  // 模板列表
  formTemplates: [],
  // 默认加载的模板
  defaultTemplate: ''
})

// 表单项类型映射
const TypeMap: any = {
  /** 表单有 */
  // 单行输入
  input: 'INPUT',
  // 多行输入
  textarea: 'TEXTAREA',
  // 计数器
  number: 'NUMBER',
  // 单选项
  radio: 'RADIO',
  // 多选项
  checkbox: 'CHECKBOX',
  // 下拉选项
  select: 'SELECT',
  // 时间
  time: 'TIME',
  // 时间范围
  'time-range': 'TIME_RANGE',
  // 日期
  date: 'DATE',
  // 日期范围
  'date-range': 'DATE_RANGE',
  // 开关
  switch: 'SWITCH',
  // 评分
  rate: 'RATE',
  // 颜色选择
  color: 'COLOUR_PICKER',
  // 滑块
  slider: 'SLIDER',
  // 静态文字
  'static-text': 'STATIC_TEXT',
  // HTML
  'html-text': '',
  // 按钮
  button: 'BUTTON',
  // 分隔线
  divider: 'DIVIDER',
  // 文件上传
  'ik-upload-file': 'FILE_UPLOAD',
  // 图片上传
  'ik-upload-image': 'IMAGE_UPLOAD',
  // 树形选择
  'tree-select': 'TREE_SELECT',

  // 人员选择
  'ik-picker': 'USER_PICKER',
  // 部门选择
  'ik-dept-picker': 'DEPT_PICKER',
  // 组织选择
  'ik-organization-picker': 'ORGANIZATION_PICKER',
  // 角色选择
  'ik-role-picker': 'ROLE_PICKER',
  // 岗位选择
  'ik-post-picker': 'POST_PICKER'

}
// 已配置的表单列表
const formList = computed<any[]>(() => {
  if (!formModel.json)
    return []
  const formList = filterForm(formModel.json.widgetList)

  const formConfig = JSON.parse(JSON.stringify(formModel.json.formConfig))

  const result = formList.map((item: any) => {
    // 将表单的表达式设置给全局配置
    formConfig.expressions = item.options.expressions

    const obj = {
      // 对应 widget.id
      code: item.id,
      name: item.options.label,
      modelId: item.options.modelId,
      widgets: item.widgetList.map((child: any) => ({
        name: child.options.keyName,
        label: child.options.label,
        type: TypeMap[child.type],
        required: child.options.required

      })),
      json: JSON.stringify({
        widgetList: item.widgetList,
        formConfig: formModel.json.formConfig
      })
    }

    return obj
  })
  if (result.length === 1)
    formModel.initiateFormId = result[0].code

  return result
})
const editMethods = {
  loadTemplate: async () => {
    const ret = await api.listTemplate()
    if (!ret.success) {
      msgError(ret.msg)
      return
    }
    const templates = ret.data.map((item: any) => ({ title: item.title, description: item.description, jsonData: JSON.parse(item.jsonData) }))
    for (const item of templates) {
      (item.jsonData.formConfig.dataSources ?? []).forEach((ds: any) => {
        ds.requestURL = `${ds.requestURL}?pageName=${formModel.name}`
      })
    }
    editState.formTemplates = templates
  },
  open: async (operation: string, record?: any) => {
    editState.operation = operation
    if (operation === 'update') {
      // TODO 将数据库里的设置数据赋值给设置器
      editState.title = '修改'
      copyValue(formModel, record)
      formModel.modelIds = record.models?.map((item: any) => item.id) ?? []
      formModel.initiateFormId = record.initiateForm?.code
    }
    else if (operation === 'add') {
      editState.title = '新增'
    }
    modelMethods.setModels()

    editState.visible = true

    if (operation === 'add') {
      nextTick(() => {
        // 若新增时选择了关联审批，则需要显示在新增时设置默认加载模板,否则，清空默认加载模板
        if (formModel.relateToApprove) {
          const template: any = editState.formTemplates.find((item: any) => item.title === '审批表格')
          if (template)
            designerRef?.value.setFormJson(template.jsonData)
        }
        else {
          designerRef.value?.clearDesigner()
        }
      })
    }
    else if (operation === 'update') {
      nextTick(() => {
        designerRef?.value.setFormJson(record.json)
      })
    }
  },
  close: () => {
    editState.visible = false
  },
  submit: async () => {
    formModel.json = designerRef.value?.getFormJson()
    if (formModel.relateToApprove)
      saveMethods.open()

    else
      saveMethods.submit()
  },
  listForm: () => {
  }
}

// onMounted(() => editMethods.loadTemplate())
/** 新增、编辑对话框 end */

/** 页面信息输入框 begin */
const saveRef = ref<any>(null)
const saveState = reactive({
  visible: false
})

const saveMethods = {
  open: () => {
    saveState.visible = true
  },
  close: () => {
    saveState.visible = false
  },
  submit: async () => {
    try {
      await saveRef.value?.validate()
    }
    catch (err) {
      return
    }

    const target = formList.value.find(item => item.code === formModel.initiateFormId)
    const params = {
      ...formModel,
      json: JSON.stringify(formModel.json),
      initiateForm: target,
      approveNodeForms: formList.value?.filter(item => item.code !== target.code) ?? []
    }

    loading.value = true
    let ret = null
    if (editState.operation === 'add')
      ret = await api.add(params)
    else
      ret = await api.update(params)

    loading.value = false
    msgSuccess(ret.msg)
    saveMethods.close()
    editMethods.close()
    search()
  }
}
/** 页面信息输入框 end */

/** 发布 begin */
const publishFormRef = ref<any>(null)
class PubmishFormModel {
  parentMenuId = ''
  menuIcon = null
}
const publishFormModel = reactive(new PubmishFormModel())

const publishState = reactive<any>({
  record: null,
  visible: false,
  menuTree: ''
})

const publishMethods = {
  close: () => {
    publishState.visible = false
  },
  open: (record: any) => {
    publishState.record = record
    copyValue(publishFormModel, record)
    publishMethods.initMenuTree()
    publishState.visible = true
  },
  confirm: (record: any) => {
    const oldStatus = record.status
    if (!oldStatus || oldStatus === 'NOT_PUBLISHED') {
      // 发布
      publishMethods.open(record)
    }
    else {
      // 取消发布
      publishMethods.cancelPublish(record)
    }
  },
  cancelPublish: async (record: any) => {
    const ret = await api.cancelPublish(record.id)
    if (!ret.success)
      return

    msgSuccess(ret.msg)
    search()
    routeStore.generateRoutesAtBack()
  },
  submit: async () => {
    let valid = false
    try {
      valid = await publishFormRef.value?.validate()
    }
    catch (err) {
    }

    if (!valid)
      return

    const params = {
      pageId: publishState.record?.id,
      ...publishFormModel
    }

    loading.value = true
    const ret = await api.publish(params)
    loading.value = false
    if (!ret.success) {
      msgError(ret.msg)
      return
    }
    msgSuccess(ret.msg)
    publishMethods.close()
    search()
    await routeStore.generateRoutesAtBack()
    routeStore.isGenerate = false
  },
  initMenuTree: () => {
    // 排序时DOM结构被更改，此操作用于正确显示排序后的结果
    publishState.menuTree = []
    menuApi
      .getUserMenuList(true)
      .then(({ success, data, msg }) => {
        if (success) {
          const menuList = data.filter((item: any) => item.menuType === 'MENU')
          publishState.menuTree = ikTree.listToTree(
            menuList.map(
              (item: any) => {
                return { key: item.id, id: item.id, parentId: item.parentId, label: item.name, value: item.id }
              }
            )
          )
        }

        else {
          msgError(msg)
        }
      })
      .catch(() => {
        publishState.menuTree = []
      })
  }
}

/** 发布 end */

/** 代码生成 begin */
const codeFormRef = ref<any>(null)
class CodeModel {
  // pageId = ''
  pageCode = ''
  packageName = ''
}
const codeFormModel = reactive(new CodeModel())
// 生成代码表单
const codeState = reactive({
  record: null as any,
  visible: false
})

const codeMethods = {
  open: (record: any) => {
    codeState.record = record
    copyValue(codeFormModel, new CodeModel())
    codeFormModel.pageCode = record.name
    codeFormRef.value?.resetFields()
    codeState.visible = true
  },
  close: () => {
    codeState.visible = false
  },
  submit: async () => {
    let valid = false
    try {
      valid = await codeFormRef.value?.validate()
    }
    catch (err) {
    }

    if (!valid)
      return

    const params = {
      pageId: codeState.record?.id,
      ...codeFormModel
    }
    const data = await api.codeGen(params)
    const { success, msg } = data
    if (success === undefined) {
      saveFile(data, { name: codeState.record.name, msgError })
      return
    }
    msgError(msg)
  }
}
/** 代码生成 end */
</script>

<template>
  <IkPageMain fixed>
    <IkPageFull
      v-model="searchData"
      header-title="页面列表"
      :fields="fields"
      :table-data="tblData"
      :total="countTotal"
      :loading="loading"
      :search="search"
      row-key="id"
    >
      <template #headerRight>
        <el-button type="primary" @click="handleAdd">新增</el-button>
      </template>

      <template #status="{ data }">
        <el-popconfirm
          :title="`确定${data.row.status === 'PUBLISHED' ? '取消发布' : '发布'}？`"
          @confirm="publishMethods.confirm(data.row)"
        >
          <template #reference>
            <el-switch
              :model-value="data.row.status"
              active-value="PUBLISHED"
              inactive-value="NOT_PUBLISHED"
              active-text="已发布"
              inactive-text="未发布"
              inline-prompt
            />
          </template>
        </el-popconfirm>
      </template>
      <template #operate="{ data }">
        <IkBtnContent :num="3">
          <IkTooltip content="生成代码">
            <IkSvgIcon
              name="iksvg_xiazai"
              show-bg
              size="small"
              @click="codeMethods.open(data.row)"
            />
          </IkTooltip>
          <IkTooltip :content="t('action.modify')">
            <IkSvgIcon
              name="iksvg_xiugai"
              show-bg
              size="small"
              @click="handleEdit(data.row)"
            />
          </IkTooltip>
          <IkTooltip :content="t('action.delete')">
            <el-popconfirm title="确定删除吗？" @confirm="handleDelete(data.row)">
              <template #reference>
                <IkSvgIcon
                  name="iksvg_shanchu1"
                  show-bg
                  size="small"
                />
              </template>
            </el-popconfirm>
          </IkTooltip>
        </IkBtnContent>
      </template>
    </IkPageFull>

    <!-- 模型选择对话框 -->
    <el-dialog v-model="modelState.visible" width="600px" title="模型选择">
      <el-form ref="modelFormRef" label-width="80px" :model="formModel">
        <el-form-item label="英文标识" :rules="[{ required: true, message: '请输入' }]">
          <el-input v-model="formModel.name" :maxlength="45" />
        </el-form-item>
        <el-form-item label="菜单名称" :rules="[{ required: true, message: '请输入' }]">
          <el-input v-model="formModel.title" :maxlength="45" />
        </el-form-item>
        <el-form-item label="菜单描述">
          <el-input v-model="formModel.description" type="textarea" :maxlength="200" />
        </el-form-item>
        <el-form-item label="业务模型">
          <el-select v-model="formModel.modelIds" multiple clearable>
            <el-option
              v-for="item in modelState.modelList"
              :key="item.code"
              :value="item.id"
              :label="item.name"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="关联审批">
          <el-switch v-model="formModel.relateToApprove" />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="modelMethods.close">取消</el-button>
        <el-button type="primary" :loading="loading" @click="modelMethods.next">
          确认
        </el-button>
      </template>
    </el-dialog>

    <!-- 页面编辑对话框 -->
    <el-dialog
      v-model="editState.visible"
      class="dialog-edit"
      fullscreen
      :title="editState.title"
    >
      <div class="designer-box">
        <v-form-designer
          v-if="editState.visible"
          ref="designerRef"
          :global-dsv="{ apiHost: baseUrl }"
          :designer-config="editState.designerConfig"
          :global-form-config="editState.globalFormConfig"
          :form-templates="editState.formTemplates"
          :global-datasource-headers="editState.globalDatasourceHeaders"
        />
      </div>
      <template #footer>
        <el-button @click="editMethods.close">取消</el-button>
        <el-button type="primary" :loading="loading" @click="editMethods.submit">
          下一步
        </el-button>
      </template>
    </el-dialog>

    <!-- 页面信息对话框 -->
    <el-dialog v-model="saveState.visible" width="500px" title="页面信息">
      <el-form ref="saveRef" :label-width="80" :model="formModel">
        <el-form-item label="发起表单" :rules="[{ required: true, message: '请选择' }]">
          <el-select v-model="formModel.initiateFormId">
            <el-option
              v-for="item in formList"
              :key="item.code"
              :value="item.code"
              :label="item.name"
            />
          </el-select>
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="saveMethods.close">取消</el-button>
        <el-button type="primary" :loading="loading" @click="saveMethods.submit">
          确认
        </el-button>
      </template>
    </el-dialog>
    <!-- 页面发布对话框 -->
    <el-dialog v-model="publishState.visible" width="500px" title="发布">
      <el-form ref="publishFormRef" label-width="66px" :model="publishFormModel">
        <el-form-item label="父级菜单">
          <el-tree-select
            v-model="publishFormModel.parentMenuId"
            check-strictly
            :data="publishState.menuTree"
            :render-after-expand="false"
            clearable
          />
        </el-form-item>
        <el-form-item label="图标" :rules="[{ required: true, message: '请选择' }]">
          <IkIconPicker v-model="publishFormModel.menuIcon" :width="60" :height="60" />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="publishMethods.close">取消</el-button>
        <el-button type="primary" :loading="loading" @click="publishMethods.submit">
          确认
        </el-button>
      </template>
    </el-dialog>

    <!-- 代码生成对话框 -->
    <el-dialog v-model="codeState.visible" title="代码生成" width="500px">
      <el-form ref="codeFormRef" label-width="80px" :model="codeFormModel">
        <el-form-item prop="packageName" label="包名" :rules="[{ required: true, message: '请输入' }]">
          <el-input v-model="codeFormModel.packageName" :maxlength="45" />
        </el-form-item>
        <el-form-item prop="pageCode" label="页面名称" :rules="[{ required: true, message: '请输入' }]">
          <el-input v-model="codeFormModel.pageCode" :maxlength="45" />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="codeMethods.close">取消</el-button>
        <el-button type="primary" :loading="loading" @click="codeMethods.submit">
          确认
        </el-button>
      </template>
    </el-dialog>
  </IkPageMain>
</template>

<style scoped lang="scss">
.publish-icon{
  width: 60px;
  height: 60px;
}

:deep(.dialog-edit .el-dialog__body){
  padding: 0;
}

:deep(.event-setting .el-dialog__body){
  padding: 28px 32px;
}

:deep(.dialog-container .el-dialog__body){
  padding: 28px 32px;
}

:deep(.setting-form .el-switch__core){
  width: 40px;
}

.designer-box{
  height: calc(100vh - 130px)
}
</style>
